package aulas.semana08.exemplosaula.livroautor;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class AutorDAO {

    private final String stmtInserir = "INSERT INTO autor(nome) VALUES(?)";
    private final String stmtConsultar = "SELECT * FROM autor WHERE id = ?";
    private final String stmtListar = "SELECT * FROM autor";
    private final String sqlAutor = "SELECT * FROM autor where nome like ?";

    public void inserirAutor(Autor autor) throws ClassNotFoundException, IOException {
        Connection con = null;
        PreparedStatement stmt = null;
        try{
            con = ConnectionFactory.getConnection();
            con.setAutoCommit(false);
            stmt = con.prepareStatement(stmtInserir,PreparedStatement.RETURN_GENERATED_KEYS);
            stmt.setString(1, autor.getNome());
            stmt.executeUpdate();
            autor.setId(lerIdAutor(stmt));
            this.gravaLivro(autor, con);
            con.commit();
        } catch (SQLException ex) {
            throw new RuntimeException("Erro ao inserir um autor no banco de dados. Origem="+ex.getMessage());
        } finally{
            try{stmt.close();}catch(Exception ex){System.out.println("Erro ao fechar stmt. Ex="+ex.getMessage());};
            try{con.close();}catch(Exception ex){System.out.println("Erro ao fechar conexão. Ex="+ex.getMessage());};
        }
     }
    public void gravaLivro(Autor autor, Connection cn) throws SQLException{
        String sql = "INSERT INTO livro(titulo) VALUES(?)";
        PreparedStatement stm;
        stm = cn.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);
        List<Livro> livros = autor.getLivros();
        for(Livro livro: livros){
            stm.setString(1, livro.getTitulo());
            stm.executeUpdate();
            this.gravaLivroAutor(lerIdAutor(stm), autor.getId(), cn);
        }
        
    }
    public void gravaLivroAutor(int idLivro,int idAutor,Connection con ) throws SQLException{
        String sql = "INSERT INTO livro_autor (idLivro, idAutor) VALUES ( ?, ?)";
        PreparedStatement stmt;
        stmt = con.prepareStatement(sql);
        stmt.setInt(1, idLivro);
        stmt.setInt(2, idAutor);
        stmt.executeUpdate();
      
    }
     
    private int lerIdAutor(PreparedStatement stmt) throws SQLException {
        ResultSet rs = stmt.getGeneratedKeys();
        rs.next();
        return rs.getInt(1);
    }

    public Autor consultarAutor(int id) throws IOException, ClassNotFoundException {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        Autor autorLido;
        try{
            con = ConnectionFactory.getConnection();
            stmt = con.prepareStatement(stmtConsultar);
            stmt.setInt(1, id);
            rs = stmt.executeQuery();
            if(rs.next()){
                autorLido = new Autor(rs.getString("nome"));
                autorLido.setId(rs.getInt("id"));
                return autorLido;
            }else{
                throw new RuntimeException("Não existe autor com este id. Id="+id);
            }
            
        } catch (SQLException ex) {
            throw new RuntimeException("Erro ao consultar um autor no banco de dados. Origem="+ex.getMessage());
        } finally{
            try{rs.close();}catch(Exception ex){System.out.println("Erro ao fechar result set. Ex="+ex.getMessage());};
            try{stmt.close();}catch(Exception ex){System.out.println("Erro ao fechar stmt. Ex="+ex.getMessage());};
            try{con.close();;}catch(Exception ex){System.out.println("Erro ao fechar conexão. Ex="+ex.getMessage());};
        }

    }

    public List<Autor> listarAutores() throws Exception {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        List<Autor> lista = new ArrayList();
        try{
            con = ConnectionFactory.getConnection();
            stmt = con.prepareStatement(stmtListar);
            rs = stmt.executeQuery();
            while(rs.next()){
                Autor autor = new Autor(rs.getString("nome"));
                autor.setId(rs.getInt("id"));
                lista.add(autor);
            }
            return lista;
        } catch (SQLException ex) {
            throw new RuntimeException("Erro ao consultar uma lista de autores. Origem="+ex.getMessage());
        }finally{
            try{rs.close();}catch(Exception ex){System.out.println("Erro ao fechar result set. Ex="+ex.getMessage());};
            try{stmt.close();}catch(Exception ex){System.out.println("Erro ao fechar stmt. Ex="+ex.getMessage());};
            try{con.close();;}catch(Exception ex){System.out.println("Erro ao fechar conexão. Ex="+ex.getMessage());};               
        }

    }
    public List<Autor> listarLivroAutor(String autor) throws SQLException, IOException, ClassNotFoundException{
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
         con = ConnectionFactory.getConnection();
            stmt = con.prepareStatement(sqlAutor);
            stmt.setString(1, autor);
            rs = stmt.executeQuery();
            List<Autor> listaAutor = new ArrayList();
            while (rs.next()) {
                List<Livro> listLivros = lerLivros(rs.getInt(1),con);
                Autor autores = new Autor(rs.getString(2), listLivros);
                autores.setId(rs.getInt(1));
                listaAutor.add(autores);
            }
        
        return listaAutor;
    } 
     private List<Livro> lerLivros(long idAutor, Connection con) throws SQLException{
        //Select para pegar os Livro de um Autor
        String sql = "SELECT livro.id,titulo"
                + " FROM livro"
                + " INNER JOIN livro_autor"
                + " 	ON livro.id = livro_autor.idlivro"
                + " WHERE livro_autor.idAutor = ? ";
        PreparedStatement stmt = null;
        List<Livro> livros = null;
        stmt = con.prepareStatement(sql);
        stmt.setLong(1, idAutor);
        ResultSet resultado = stmt.executeQuery();
        livros = new ArrayList();
        while (resultado.next()) {
            Livro livrolido = new Livro(resultado.getString("titulo"));
            livrolido.setId(resultado.getInt("id"));
            livros.add(livrolido);
        }

        return livros;
    }

}
